<?php

namespace App;

use App\Models\DoctorDetail;
use App\Models\DrugDictionary;
use App\Models\Hospital;
use App\Models\MedicalRecord;
use App\Models\Patient;
use App\Models\Reservation\Reservation;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Silber\Bouncer\Database\HasRolesAndAbilities;

class User extends Authenticatable
{
    use Notifiable, SoftDeletes, HasRolesAndAbilities;

    /**
     * @var array
     */
    protected $dates = ['deleted_at'];

    protected $table = 'tn_user_base';

    /**
     * The attributes that are mass assignable.
     * @var array
     */
    protected $fillable = [
        'name', 'phone', 'sex', 'password', 'hospital_id', 'department', 'province', 'city', 'county', 'nation',
        'birthday', 'show_mobile', 'invite_code', 'invite_original_code', 'invite_type', 'account', 'rong_token'
    ];

    /**
     * The attributes that should be hidden for arrays.
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token', 'api_token'
    ];

    protected static function boot()
    {
        parent::boot();

        //  全局作用域
        static::addGlobalScope('role', function (Builder $builder) {
            $builder->whereIn('tn_user_base.type', [0, 2, 3, 4]);
        }
        );
    }

    /**
     * @param      $id
     * @param bool $withTrashed
     * @return static
     */
    public function getWithCache($id, $withTrashed = true)
    {
        return \Cache::remember(
            $this->getTable() . ':' . $this->getKeyName() . ':' . $id,
            60,
            function () use ($id, $withTrashed) {

                $user = new static();

                if ($withTrashed) {
                    $user = $user->withTrashed();
                }

                return $user->findOrFail($id);
            });
    }

    public function scopeOnlyDoctors(Builder $builder)
    {
        return $builder->withoutGlobalScope('role')->whereIn('tn_user_base.type', [2, 3, 4]);
    }

    public function scopeSimpleField(Builder $builder)
    {
        return $builder->select(
            [
                'id', 'account', 'name', 'sex', 'age', 'birthday', 'phone', 'type', 'email', 'nation', 'hospital_id',
                'deleted_at', 'created_at', 'updated_at',
            ]
        );
    }

    public function male()
    {
        return $this->sex['key'] == 0;
    }

    public function female()
    {
        return $this->sex['key'] == 1;
    }

    public function isAdmin()
    {
        return $this->type == 0;
    }

    public function isPatient()
    {
        return $this->type == 1;
    }

    public function isDoctor()
    {
        return $this->type == 2;
    }

    public function isDoctorsAdmin()
    {
        return $this->type == 3;
    }

    public function isRegionAdmin()
    {
        return $this->type == 4;
    }

    public function isDelAdmin()
    {
        $result = 0;
        $admin_ids = config('admin.admin_ids');

        if (in_array($this->id, $admin_ids)) {
            $result = 1;
        }

        return $result;
    }
    //  预约相关

    /**
     * 是否可以进行预约
     * @return bool
     */
    public function canReservation()
    {
        //return $this->hospital->can('reservation') || $this->isAn('admin');
        return $this->hospital->type==1 || $this->isAn('admin');
    }

    public function reservations()
    {
        return $this->belongsToMany(Patient::class, 'reservation')
            ->using(Reservation::class)
            ->withTimestamps();
    }

    //  预约相关

    public function getCreatetimeAttribute($value)
    {
        return date('Y-m-d H:i:s', $value);
    }

    public function getSexAttribute($value)
    {
        if ($value) {
            $sex = '女';
        } else {
            $sex = '男';
        }

        return ['key' => $value, 'value' => $sex];
    }

    public function getNationAttribute($value)
    {
        if (empty($value)) {
            return ['key' => 0, 'value' => '未填写'];
        }

        $nation = app('field')->get('nation');

        if (is_numeric($value)) {
            return ['key' => $value, 'value' => $nation[$value]];
        }

        $key = array_search($value, $nation);

        return ['key' => $key ? $key : null, 'value' => $value];
    }

    public function setNationAttribute($value)
    {
        if (is_numeric($value)) {

            $nation = app('field')->get('nation');

            $this->attributes['nation'] = $nation[$value];
        } else {
            $this->attributes['nation'] = $value;
        }
    }

    public function setBirthdayAttribute($value)
    {
        if (('0000-00-00' == $value) || '' === $value) {
            $this->attributes['birthday'] = null;
            $this->attributes['age'] = 0;
        } else {
            $this->attributes['birthday'] = $value;
            $this->attributes['age'] = Carbon::parse($value)->age;
        }
    }

    public function setPasswordAttribute($value)
    {
        return $this->attributes['password'] = md5($value);
    }

    public function getBirthdayAttribute($value)
    {
        return is_null($value) ? '' : $value;
    }

    public function getAgeAttribute($value)
    {
        return (is_null($value) || '' === $value)
            ? $this->birthday ? Carbon::parse($this->birthday)->age : '暂无'
            : $value;
    }

    /**
     * 医生看诊的病历
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function medicalRecords()
    {
        return $this->hasMany(MedicalRecord::class, 'doctor_id');
    }

    /**
     * 医生所属的医院
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function hospital()
    {
        return $this->belongsTo(Hospital::class);
    }

    /**
     * 医生添加的用药
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function drugs()
    {
        return $this->hasMany(DrugDictionary::class, 'doctor_id');
    }

    public function detail()
    {
        return $this->hasOne(DoctorDetail::class, 'account', 'account');
    }
}
